package com.liuzy;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Reader;
import java.net.Socket;
import java.util.Scanner;

/**
 * 执行Client的CMD命令
 * 
 * @author liuzy
 * @version 2015年5月1日
 */
public class Task extends Thread {
	/** 任务工作状态标志 */
	private boolean isRun = true;
	/** 客户端套节字 */
	private Socket socket;
	/** 客户端编号 */
	private int id;
	/** 客户端的输入 */
	private InputStream in;
	/** 客户端的输出 */
	private OutputStream out;
	/** 统一状态 */
	private boolean status = false;
	/** 统一状态码 */
	private String statusCode = null;
	/** 已输入密码错误次数 */
	private int pwdCount = 0;
	/** 执行cmd.exe的进程 */
	private Process p = null;
	/** cmd.exe的正常消息输出进程 */
	private Thread inThread = null;
	/** cmd.exe错误消息输出进程 */
	private Thread outThread = null;
	
	public Task(Socket socket, int id) {
		this.socket = socket;
		this.id = id;
		try {
			this.in = socket.getInputStream();
			this.out = socket.getOutputStream();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void run() {
		try {
			System.out.println("客户端" + id + "已连接! " + this.toString());
			p = Runtime.getRuntime().exec("cmd");
			// 把cmd.exe返回的正常消息流按字符写到客户端的out
			inThread = new Thread(new Runnable() {
				@Override
				public void run() {
					try {
						boolean flag = true;
						Reader reader = new InputStreamReader(Task.this.p.getInputStream(), "GBK");
						int size = -1;
						char[] buf = new char[1024];
						while (true) {
							size = reader.read(buf);
							if (size != -1) {
								if (flag) {
									// 去掉版本信息
									for (int i = 0; i < buf.length; i++) {
										if (buf[i] == ':') {
											Task.this.writeClient(new String(buf, i-1, size).getBytes("UTF-8"));
											flag = false;
											break;
										}
									}
								} else {
									Task.this.writeClient(new String(buf, 0, size).getBytes("UTF-8"));
								}
							} else {
								break;
							}
						}
						reader.close();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			});
			inThread.start();
			// 把cmd.exe返回的错误消息流按字符写到客户端的out
			outThread = new Thread(new Runnable() {
				@Override
				public void run() {
					try {
						Reader reader = new InputStreamReader(Task.this.p.getErrorStream(), "GBK");
						int size = -1;
						char[] buf = new char[1024];
						while (true) {
							size = reader.read(buf);
							if (size != -1) {
								Task.this.writeClient(new String(buf, 0, size-1).getBytes("UTF-8"));
							} else {
								break;
							}
						}
						reader.close();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			});
			outThread.start();
			this.writeClient("**************\r\ncmd.exe已打开!\r\n如需帮助请输入help回车.\r\n**************\r\n");
			Scanner scanner = new Scanner(in);
			while (isRun && scanner.hasNextLine()) {
				final String line = scanner.nextLine().trim();
				if(!"".equals(line)) {
					System.out.println("客户端" + id + ":" + line);
					if (status) {
						switch (statusCode) {
						case "pwd":
							if ("111111".equals(line)) {
								this.writeClient("再见!\r\n");
								Server.shutdown();
								break;
							} else {
								++pwdCount;
								if (pwdCount > 2) {
									this.writeClient("错误!\r\n");
									this.setStatus(false, "");
									pwdCount = 0;
									continue;
								}
								this.writeClient("再输入密码:");
							}
							break;
						case "1":
							break;
						case "2":
							break;
						default:
							break;
						}
					} else {
						switch (line) {
						case "status":
							this.writeClient(Server.getStatus());
							break;
						case "exit":
							this.writeClient("\r\n再见!\r\n");
							this.stopTask();
							break;
						case "shutdown":
							this.writeClient("请输入密码:");
							this.setStatus(true, "pwd");
							break;
						case "help":
							this.writeClient("CMD命令服务 作者:liuzy\r\n**************\r\nstatus 显示服务状态\r\nexit 退出当前连接\r\nshutdown 停止服务关闭所有连接,需操作密码\r\nhelp 显示此帮助\r\n");
							break;
						case "stop 1":
							Server.stopTask(1);
							break;
						default:
							// 把当前字符串写到cmd.exe
							PrintWriter pw = new PrintWriter(p.getOutputStream());
							pw.println(line);
							pw.flush();
							break;
						}
					}
				} else {
					// 把\n写到cmd.exe
					PrintWriter pw = new PrintWriter(p.getOutputStream());
					pw.println("\n");
					pw.flush();
				}
			}
			scanner.close();
			p.destroy();
			Server.removeTask(id);
			System.out.println("客户端" + id + "已退出!");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private void writeClient(String msg) {
		try {
			out.write(msg.getBytes());
			out.flush();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private void writeClient(byte[] bytes) {
		try {
			out.write(bytes);
			out.flush();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private void setStatus(boolean status, String statusCode) {
		this.status = status;
		this.statusCode = statusCode;
	}
	
	public void stopTask() {
		this.isRun = false;
		try {
			socket.shutdownOutput();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public String toString() {
		StringBuffer sb = new StringBuffer();
		sb.append("[").append(socket.getInetAddress().toString().replace("/", "")).append(":")
		.append(socket.getPort()).append("]");
		return sb.toString();
	}
	
}
